package com.qfedu.fmmall.service.impl;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qfedu.fmmall.dao.UsersMapper;
import com.qfedu.fmmall.entity.Users;
import com.qfedu.fmmall.service.UserService;
import com.qfedu.fmmall.utils.Base64Utils;
import com.qfedu.fmmall.utils.MD5Utils;
import com.qfedu.fmmall.vo.ResultStatus;
import com.qfedu.fmmall.vo.ResultVo;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements UserService {

   @Autowired
    private UsersMapper usersMapper;


   @Autowired
   private StringRedisTemplate stringRedisTemplate;

   private ObjectMapper objectMapper = new ObjectMapper();

    @Transactional  //开始事务  防止出现两个用户注册相同账号的情况
    public ResultVo userResgit(String username, String password) {
      synchronized (this){ //让注册服务统一在同一线程中
          Example example = new Example(Users.class);
          Example.Criteria criteria = example.createCriteria();
          criteria.andEqualTo("username",username);

          List<Users> users = usersMapper.selectByExample(example);
          if(users.size()==0){
              String md5Pwd = MD5Utils.md5(password);
              Users user = new Users();
              user.setUsername(username);
              user.setUserImg("img/default.png");
              user.setPassword(md5Pwd);
              user.setUserModtime(new Date());
              user.setUserRegtime(new Date());
              int i = usersMapper.insert(user);
              if(i>0){
                  return  new ResultVo(ResultStatus.OK,"注册成功",user);
              }else{
                  return  new ResultVo(ResultStatus.NO,"注册失败",null);
              }
          }else{
              return  new ResultVo(ResultStatus.NO,"该用户已注册",null);
          }
      }


    }

    @Override
    public ResultVo checkLogin(String username, String password) {
        Example example = new Example(Users.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("username", username);

        List<Users> user = usersMapper.selectByExample(example);
        if(user == null){
            return  new ResultVo(ResultStatus.NO,"该用户不存在",null);
        }else{
            String md5Pwd = MD5Utils.md5(password);
            if(md5Pwd.equals(user.get(0).getPassword())){
//                String token = Base64Utils.encode(username + "QIANfeng6666");
                HashMap<String,Object> map = new HashMap<>();
                map.put("key1","value1");
                map.put("key2","value2");
                //如果登录验证成功，则需要生成令牌token (token就是按照特定规则生成的字符串)
                //使用jwt 规则生成token字符串
                JwtBuilder builder = Jwts.builder();

                String token = builder.setSubject(username) //主题，就是token 中携带的数据
                        .setIssuedAt(new Date())     //设置token 的生成时间
                        .setId(user.get(0).getUserId() + "")//设置用户id为token  id
                        .setClaims(map) //map 中可以存放用户的角色权限信息、
                        .setExpiration(new Date(System.currentTimeMillis() + 24*60*60*1000)) //设置过期时间
                        .signWith(SignatureAlgorithm.HS256, "QIANFeng6666") //设置加密方式和加密密码
                        .compact();

                try {
                    String userData = objectMapper.writeValueAsString(user.get(0));
                    stringRedisTemplate.boundValueOps(token).set(userData,30, TimeUnit.MINUTES);
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }


                return  new ResultVo(ResultStatus.OK,token,user.get(0));
            }else{
                return  new ResultVo(ResultStatus.NO,"密码错误",null);
            }
        }

    }
}
